
/*
//I Love U 向下移动
#include<reg52.h>

sbit ADDR0=P1^0;
sbit ADDR1=P1^1;
sbit ADDR2=P1^2;
sbit ADDR3=P1^3;
sbit ENLED=P1^4;

//把取模放数组里
unsigned char code image[]={
    0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x99,0x99,0x99,0x99,0x99,0x99,0x81,0xC3,
0xFF,0x99,0x00,0x00,0x00,0x81,0xC3,0xE7,0xFF,0xC3,0xE7,0xE7,0xE7,0xE7,0xE7,0xC3,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
};

void main()
{
    EA=1;//中断总开关
    ENLED=0;//U4  74HC138
    ADDR3=0;
    TMOD=0x01;//定时器0打开
    TH0=0xFC;//定时1ms
    TL0=0x67;
    ET0=1;//定时器0中断
    TR0=1;
    while(1);
}
//中断函数
void InterruptTimer() interrupt 1
{
    static unsigned char i=0;//静态变量（行数） 初始化从第一行开始
    static unsigned char index=31;//从最后一张开始 显示8*8   显示图片张数
    static unsigned char timer=0;//250ms软件定时
    TH0=0xFC;//定时1ms
    TL0=0x67;
    P0=0xFF;//先关闭  初始化  //消除鬼影----消隐

    switch(i)  //从0-7到1-8到2-9......
    {
        case 0:ADDR0=0;ADDR1=0;ADDR2=0;i++;P0=image[index+0];break;
        case 1:ADDR0=1;ADDR1=0;ADDR2=0;i++;P0=image[index+1];break;
        case 2:ADDR0=0;ADDR1=1;ADDR2=0;i++;P0=image[index+2];break;
        case 3:ADDR0=1;ADDR1=1;ADDR2=0;i++;P0=image[index+3];break;
        case 4:ADDR0=0;ADDR1=0;ADDR2=1;i++;P0=image[index+4];break;
        case 5:ADDR0=1;ADDR1=0;ADDR2=1;i++;P0=image[index+5];break;
        case 6:ADDR0=0;ADDR1=1;ADDR2=1;i++;P0=image[index+6];break;
        case 7:ADDR0=1;ADDR1=1;ADDR2=1;i=0;P0=image[index+7];break;
        default:break;
    }
    timer++;
    if(timer>=250)  //250ms切换一张图片
    {
        timer=0;
        if(index==0)  //31->0张循环
        {
            index=31;  //
        }
        else
        {
            index--;
        }
    }
}
*/




/*
//点阵显示 9->0倒计时
#include<reg52.h>

sbit ADDR0=P1^0;
sbit ADDR1=P1^1;
sbit ADDR2=P1^2;
sbit ADDR3=P1^3;
sbit ENLED=P1^4;

//把取模放数组里
unsigned char code image[11][8]={
    {0xFF,0xC3,0xDB,0xDB,0xDB,0xDB,0xC3,0xFF,},// 0
    {0xF7,0xF3,0xF7,0xF7,0xF7,0xF7,0xC1,0xFF,},
    {0xFF,0xC3,0xDF,0xDF,0xC3,0xFB,0xFB,0xC3,},
    {0xFF,0xC3,0xDF,0xDF,0xC3,0xDF,0xDF,0xC3,},
    {0xFF,0xE7,0xEB,0xED,0x81,0xEF,0xEF,0xEF,},
    {0xFF,0xC3,0xFB,0xC3,0xDF,0xDF,0xC3,0xFF,},
    {0xFF,0xC3,0xFB,0xFB,0xC3,0xDB,0xDB,0xC3,},
    {0xFF,0xC3,0xDF,0xDF,0xDF,0xDF,0xDF,0xFF,},
    {0xFF,0xC3,0xDB,0xDB,0xC3,0xDB,0xDB,0xC3,},
    {0xFF,0xC3,0xDB,0xDB,0xC3,0xDF,0xDF,0xC3,},// 9
    {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,}  // 全亮

};

void main()
{
    EA=1;//中断总开关
    ENLED=0;//U4  74HC138
    ADDR3=0;
    TMOD=0x01;//定时器0打开
    TH0=0xFC;//定时1ms
    TL0=0x67;
    ET0=1;//定时器0中断
    TR0=1;
    while(1);
}
//中断函数
void InterruptTimer() interrupt 1
{
    static unsigned char i=0;//动态变量（行数） 初始化从第一行开始
    static unsigned char index=9;// 显示8*8   显示图片张数    
    static unsigned int timer=0;//250ms软件定时   1000----65535(int)
    TH0=0xFC;//定时1ms
    TL0=0x67;
    P0=0xFF;//先关闭  初始化  //消除鬼影----消隐

    switch(i)  //从0-7到1-8到2-9......
    {
        case 0:ADDR0=0;ADDR1=0;ADDR2=0;i++;P0=image[index][0];break;
        case 1:ADDR0=1;ADDR1=0;ADDR2=0;i++;P0=image[index][1];break;
        case 2:ADDR0=0;ADDR1=1;ADDR2=0;i++;P0=image[index][2];break;
        case 3:ADDR0=1;ADDR1=1;ADDR2=0;i++;P0=image[index][3];break;
        case 4:ADDR0=0;ADDR1=0;ADDR2=1;i++;P0=image[index][4];break;
        case 5:ADDR0=1;ADDR1=0;ADDR2=1;i++;P0=image[index][5];break;
        case 6:ADDR0=0;ADDR1=1;ADDR2=1;i++;P0=image[index][6];break;
        case 7:ADDR0=1;ADDR1=1;ADDR2=1;i=0;P0=image[index][7];break;
        default:break;
    }
    //每秒改变一帧图像
    timer++;
    if(timer>=1000)  //1s切换一张图片
    {
        timer=0;
        if(index==0)  //9->0张循环
        {
            index=10; //返回0 循环
        }
        else
        {
            index--;
        }
    }
}
*/




/*
//流水灯  数码管   点阵 同时全亮
#include<reg52.h>

sbit ADDR0=P1^0;
sbit ADDR1=P1^1;
sbit ADDR2=P1^2;
sbit ADDR3=P1^3;
sbit ENLED=P1^4;

//把取模放数组里
unsigned char code image[11][8]={
    {0xFF,0xC3,0xDB,0xDB,0xDB,0xDB,0xC3,0xFF,},// 0
    {0xF7,0xF3,0xF7,0xF7,0xF7,0xF7,0xC1,0xFF,},
    {0xFF,0xC3,0xDF,0xDF,0xC3,0xFB,0xFB,0xC3,},
    {0xFF,0xC3,0xDF,0xDF,0xC3,0xDF,0xDF,0xC3,},
    {0xFF,0xE7,0xEB,0xED,0x81,0xEF,0xEF,0xEF,},
    {0xFF,0xC3,0xFB,0xC3,0xDF,0xDF,0xC3,0xFF,},
    {0xFF,0xC3,0xFB,0xFB,0xC3,0xDB,0xDB,0xC3,},
    {0xFF,0xC3,0xDF,0xDF,0xDF,0xDF,0xDF,0xFF,},
    {0xFF,0xC3,0xDB,0xDB,0xC3,0xDB,0xDB,0xC3,},
    {0xFF,0xC3,0xDB,0xDB,0xC3,0xDF,0xDF,0xC3,},// 9
    {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,}  // 全亮

};

void main()
{
    EA=1;//中断总开关
    ENLED=0;//U4  74HC138
    //ADDR3=0;  转化为局部  控制U3(数码管、流水灯) U4(点阵)
    TMOD=0x01;//定时器0打开
    TH0=0xFC;//定时1ms
    TL0=0x67;
    ET0=1;//定时器0中断
    TR0=1;
    while(1);
}
//中断函数
void InterruptTimer() interrupt 1
{
    static unsigned char i=0;//动态变量（行数） 初始化从第一行开始
    static unsigned char index=9;// 显示8*8   显示图片张数    
    static unsigned int timer=0;//250ms软件定时   1000----65535(int)
    TH0=0xFC;//定时1ms
    TL0=0x67;
    P0=0xFF;//先关闭  初始化  //消除鬼影----消隐

    switch(i)  //从0-7到1-8到2-9......
    {
        //点阵LED
        case 0:ADDR3=0;ADDR0=0;ADDR1=0;ADDR2=0;i++;P0=0;break;
        case 1:ADDR3=0;ADDR0=1;ADDR1=0;ADDR2=0;i++;P0=0;break;
        case 2:ADDR3=0;ADDR0=0;ADDR1=1;ADDR2=0;i++;P0=0;break;
        case 3:ADDR3=0;ADDR0=1;ADDR1=1;ADDR2=0;i++;P0=0;break;
        case 4:ADDR3=0;ADDR0=0;ADDR1=0;ADDR2=1;i++;P0=0;break;
        case 5:ADDR3=0;ADDR0=1;ADDR1=0;ADDR2=1;i++;P0=0;break;
        case 6:ADDR3=0;ADDR0=0;ADDR1=1;ADDR2=1;i++;P0=0;break;
        case 7:ADDR3=0;ADDR0=1;ADDR1=1;ADDR2=1;i++;P0=0;break;

        //数码管
        case 8:ADDR3=1;ADDR0=0;ADDR1=0;ADDR2=0;i++;P0=0;break;
        case 9:ADDR3=1;ADDR0=1;ADDR1=0;ADDR2=0;i++;P0=0;break;
        case 10:ADDR3=1;ADDR0=0;ADDR1=1;ADDR2=0;i++;P0=0;break;
        case 11:ADDR3=1;ADDR0=1;ADDR1=1;ADDR2=0;i++;P0=0;break;
        case 12:ADDR3=1;ADDR0=0;ADDR1=0;ADDR2=1;i++;P0=0;break;
        case 13:ADDR3=1;ADDR0=1;ADDR1=0;ADDR2=1;i++;P0=0;break;

        //独立LED
        case 14:ADDR3=1;ADDR0=0;ADDR1=1;ADDR2=1;i=0;P0=0;break;
        default:break;
    }
}
*/




/*
//数码管动态显示，无中断样改   ---函数调用
//主函数放在前面    中断函数放在最后    其他函数放主函数后需要定义---让主函数知道有其他函数被找到并调用

#include <reg52.h>

sbit ADDR0 = P1^0;
sbit ADDR1 = P1^1;
sbit ADDR2 = P1^2;
sbit ADDR3 = P1^3;
sbit ENLED = P1^4;

unsigned char code LedChar[] = {  //数码管显示字符转换表
    0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8,
    0x80, 0x90, 0x88, 0x83, 0xC6, 0xA1, 0x86, 0x8E
};
unsigned char LedBuff[6] = {  //数码管显示缓冲区，初值0xFF确保启动时都不亮
    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
};

void SecondCount();//定义函数
void LedRefresh();

void main()
{
    ENLED = 0;    //使能U3，选择控制数码管
    ADDR3 = 1;    //因为需要动态改变ADDR0-2的值，所以不需要再初始化了
    TMOD = 0x01;  //设置T0为模式1
    TH0  = 0xFC;  //为T0赋初值0xFC67，定时1ms
    TL0  = 0x67;
    TR0  = 1;     //启动T0
    
    while (1)
    {
        if (TF0 == 1)         //判断T0是否溢出
        {
            TF0 = 0;          //T0溢出后，清零中断标志
            TH0 = 0xFC;       //并重新赋初值
            TL0 = 0x67;
            SecondCount();//调用秒计数函数
            LedRefresh();//调用动态扫描刷新函数
        }
    }
}


//秒计数函数，+1转化一次字符
void SecondCount()
{
    static unsigned int  cnt = 0;  //记录T0中断次数
    static unsigned long sec = 0;  //记录经过的秒数

    cnt++;            //计数值自加1
    if (cnt >= 1000)  //判断T0溢出是否达到1000次
    {
        cnt = 0;      //达到1000次后计数值清零
        sec++;        //秒计数自加1
        //以下代码将sec按十进制位从低到高依次提取并转为数码管显示字符
        LedBuff[0] = LedChar[sec%10];
        LedBuff[1] = LedChar[sec/10%10];
        LedBuff[2] = LedChar[sec/100%10];
        LedBuff[3] = LedChar[sec/1000%10];
        LedBuff[4] = LedChar[sec/10000%10];
        LedBuff[5] = LedChar[sec/100000%10];
    }
}

//动态扫描刷新函数
void LedRefresh()
{
    static unsigned char i = 0;    //动态扫描的索引
    //以下代码完成数码管动态扫描刷新
    switch (i)
    {
        case 0: ADDR2=0; ADDR1=0; ADDR0=0; i++; P0=LedBuff[0]; break;
        case 1: ADDR2=0; ADDR1=0; ADDR0=1; i++; P0=LedBuff[1]; break;
        case 2: ADDR2=0; ADDR1=1; ADDR0=0; i++; P0=LedBuff[2]; break;
        case 3: ADDR2=0; ADDR1=1; ADDR0=1; i++; P0=LedBuff[3]; break;
        case 4: ADDR2=1; ADDR1=0; ADDR0=0; i++; P0=LedBuff[4]; break;
        case 5: ADDR2=1; ADDR1=0; ADDR0=1; i=0; P0=LedBuff[5]; break;
        default: break;
    }
}
*/




/*
//矩阵按键转化为独立按键  
//按下 对应的LED点亮，没自锁

#include<reg52.h>
sbit ADDR0=P1^0;
sbit ADDR1=P1^1;
sbit ADDR2=P1^2;
sbit ADDR3=P1^3;
sbit ENLED=P1^4;
//四个LED小灯
sbit LED6=P0^4;
sbit LED7=P0^5;
sbit LED8=P0^6;
sbit LED9=P0^7;

//四个按键
sbit KEY1=P2^4;
sbit KEY2=P2^5;
sbit KEY3=P2^6;
sbit KEY4=P2^7;

void main()
{
    //打开led小灯总开关
    ENLED=0;
    ADDR3=1;
    ADDR0=0;
    ADDR1=1;
    ADDR2=1;

    P2=0xF7;
    while(1)
    {
        LED9=KEY1;
        LED8=KEY2;
        LED7=KEY3;
        LED6=KEY4;

    }
}
*/




/*
//数码管按键 加自锁功能
#include<reg52.h>
sbit ADDR0=P1^0;
sbit ADDR1=P1^1;
sbit ADDR2=P1^2;
sbit ADDR3=P1^3;
sbit ENLED=P1^4;
//四个LED小灯
sbit LED6=P0^4;
sbit LED7=P0^5;
sbit LED8=P0^6;
sbit LED9=P0^7;


//每按一下就加一
sbit KEY4=P2^7;

unsigned char code LedChar[] = {  //数码管显示字符转换表   0-F
    0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8,
    0x80, 0x90, 0x88, 0x83, 0xC6, 0xA1, 0x86, 0x8E
};

void main()
{
    unsigned char cnt=0;//按下次数
    bit backup=1; // 51单片机特有的   八位 每一位只有两种状态 0 1 //保存前一次扫描的按键值
    //按下0 弹起1
    //打开led小灯总开关
    ENLED=0;
    ADDR3=1;
    ADDR0=0;
    ADDR1=0;
    ADDR2=0;
    P2=0xF7;
    P0=LedChar[cnt];//显示按下次数初值
    while(1)
    {
        if(KEY4!=backup)//与前次不等  按键有动作
        {
            if(backup==0)//当前值为0，由0变1，按键弹起
            {
                cnt++;
                if(cnt>=16)//显示0-F循环
                {
                    cnt=0;
                }
                P0=LedChar[cnt];//计数值显示到数码管上
            }
            backup=KEY4;//更新备份为当前值，循环比较
        }
    }
}
*/




//用延时消除抖动-------在实际工程中禁用delay()
#include<reg52.h>
sbit ADDR0=P1^0;
sbit ADDR1=P1^1;
sbit ADDR2=P1^2;
sbit ADDR3=P1^3;
sbit ENLED=P1^4;
//四个LED小灯
sbit LED6=P0^4;
sbit LED7=P0^5;
sbit LED8=P0^6;
sbit LED9=P0^7;


//每按一下就加一
sbit KEY4=P2^7;

unsigned char code LedChar[] = {  //数码管显示字符转换表   0-F
    0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8,
    0x80, 0x90, 0x88, 0x83, 0xC6, 0xA1, 0x86, 0x8E
};

void delay();//声明延时

void main()
{
    bit keybuf=1;//按键值暂存
    unsigned char cnt=0;//按下次数
    bit backup=1; // 51单片机特有的   八位 每一位只有两种状态 0 1 //保存前一次扫描的按键值
    //按下0 弹起1
    //打开led小灯总开关
    ENLED=0;
    ADDR3=1;
    ADDR0=0;
    ADDR1=0;
    ADDR2=0;
    P2=0xF7;
    P0=LedChar[cnt];//显示按下次数初值
    while(1)
    {
        keybuf=KEY4;//当前扫描值暂存
        if(keybuf!=backup)//与前次不等  按键有动作
        {
            delay();//延时10ms
            if(keybuf==KEY4)//判断扫描值有没有改变，即按键抖动
            {
                if(backup==0)//当前值为0，由0变1，按键弹起
                {
                    cnt++;
                    if(cnt>=16)//显示0-F循环
                    {
                        cnt=0;
                    }
                    P0=LedChar[cnt];//计数值显示到数码管上
                }
                backup=keybuf;//更新备份为当前值，循环比较
            }
           
        }
    }
}
//软件延时 10ms
void delay()
{
    unsigned int i=1000;
    while(i--);
}

